package com.study.talk.netty;

import android.util.Log;

import com.study.talk.netty.message.AndroidChannelInitializer;
import com.study.common.event.Constants;
import com.study.common.EventBusUtil;
import com.study.common.event.OtherMessage;
import com.study.talk.netty.message.TalkMessage;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

public class NettyClient {

    public static String TAG = "NettyClient";

    private static Channel channel;

    private static final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);


    public static void start(String ip, Integer port) {
        Log.i(TAG, "start:客户端启动...");
        NioEventLoopGroup group = new NioEventLoopGroup();
        AndroidChannelInitializer initializer = new AndroidChannelInitializer();
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(ip, port)).handler(initializer).option(ChannelOption.TCP_NODELAY, true).option(ChannelOption.SO_KEEPALIVE, true);
            connect(ip, port, bootstrap, 5);
            scheduledExecutorService.scheduleWithFixedDelay(() -> {
                if (channel == null || !channel.isActive() || !channel.isOpen() || !channel.isWritable()) {
                    Log.e(TAG, "connect: 尝试重新连接");
                    connect(ip, port, bootstrap, 1);
                }
            }, 10, 10, TimeUnit.SECONDS);
        } catch (Exception e) {
            //ToastUtil.showToast(context, "网络连接中...估计服务器没开");
        }
    }

    private static void connect(String ip, Integer port, Bootstrap bootstrap, final int retry) {
        bootstrap.connect(ip, port).addListener(future -> {
            if (future.isSuccess()) {
                Log.d(TAG, "connect: 启动连接成功");
                boolean needLogin = false;
                if (channel != null) {
                    channel.close();
                    needLogin = true;
                }
                channel = ((ChannelFuture) future).channel();
                if (needLogin) {
                    reLogin(channel);
                }

            } else if (retry == 0) {
                Log.e(TAG, "connect: 不再重试连接");
                scheduledExecutorService.shutdownNow();
                EventBusUtil.sendEvent(new OtherMessage(Constants.CONNECTION_ERROR));
            } else {
                int sleepSecond = 1 << retry;
                Thread.sleep(sleepSecond);
                connect(ip, port, bootstrap, retry - 1);
            }
        });
    }


    //TODO 保存用户名和密码后重新登录
    private static void reLogin(Channel channelCache) {

    }

    public static void sendMessage(TalkMessage message) {

        //连接还在，发送消息
        if (channel.isActive()) {
            channel.writeAndFlush(message);
        } else {
            //全局通知断开连接
            EventBusUtil.sendEvent(new OtherMessage(Constants.EVENT_NETTY_DISCONNECT));
        }
    }

    public static void close() {
        Executors.newSingleThreadExecutor().submit(() -> {
            if (channel != null) {
                channel.close();
                channel = null;
            }
        });
    }

}
